/**
 * Copyright (c) 2010, QinJian
 * All rights reserved.
 */
package com.q.course.service.arrange;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.hibernate.annotations.common.util.StringHelper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.q.course.dao.arrange.ArrangeDao;
import com.q.course.dao.category.CategoryDao;
import com.q.course.dao.classes.ClassesDao;
import com.q.course.dao.user.UserDao;
import com.q.course.entity.arrange.Arrange;
import com.q.course.entity.arrange.Event;
import com.q.course.entity.category.Category;
import com.q.course.entity.classes.Classes;
import com.q.course.entity.user.User;

/**
 * @author 覃健,Email:j411@qq.com
 *
 */
@Component
@Transactional
public class ArrangeService {

	@Autowired
	private ArrangeDao arrangeDao;
	@Autowired
	private CategoryDao categoryDao;
	@Autowired
	private UserDao userDao;
	@Autowired
	private ClassesDao classesDao;
	
	public ArrayList<Event> saveArrange( Arrange arrange ){
//		Category course = categoryDao.findOne( arrange.getCourseId() );
//		int cnum = course.getClassHour();//总课时数
		int cnum = arrange.getClassHourSum()!=null?arrange.getClassHourSum():0;
		int chour = arrange.getClassHour();
		Date sDate = arrange.getStartTime();
		Date eDate = arrange.getEndTime();
		int classNum = arrange.getNumber();
		
		char[] checkdays = checkedDays(arrange.getArrangeLaw());
		Long[] checktimes = checkedTimes(arrange.getArrangeLaw());
		Long[] checkplaces = checkedPlaces(arrange.getArrangeLaw());
		
		ArrayList<Event> evs = new ArrayList<Event>(cnum);
		if( checkdays!=null ){
			Calendar calendar = Calendar.getInstance();
			
			for (int i = 0; i < cnum; ) {
				
				for (int j = 0; j < checkdays.length; j++) {
					
					Arrange arrange2 = new Arrange();
					BeanUtils.copyProperties(arrange, arrange2);
					arrange2.setStartTime( sDate ); 
					arrange2.setEndTime( eDate );
					arrange2.setNumber(classNum);
					calendar.setTime(sDate);
					Integer today = calendar.get(Calendar.DAY_OF_WEEK);
					
					if( String.valueOf( checkdays[j] ).equals( today.toString() ) ){
						Category times = categoryDao.findOne(checktimes[j]);
						//因只能采用快捷时间中的小时分钟，所以需要sDate的日期 + 快捷时间的小时分钟形成准确时间
						
						long sDateTime = sDate.getTime();
						int sDateHour = calendar.get(Calendar.HOUR_OF_DAY);
						int sDateMinute = calendar.get(Calendar.MINUTE);
						//日期毫秒
						sDateTime = sDateTime - sDateHour*60*60*1000 - sDateMinute*60*1000;
						
						calendar.setTime(times.getStartTime());
						arrange2.setStartTime( new Date( sDateTime + calendar.get(Calendar.HOUR_OF_DAY)*60*60*1000 + calendar.get(Calendar.MINUTE)*60*1000 ) );
						calendar.setTime(times.getEndTime());
						arrange2.setEndTime( new Date( sDateTime + calendar.get(Calendar.HOUR_OF_DAY)*60*60*1000 + calendar.get(Calendar.MINUTE)*60*1000 ) );
						
						
						arrange2.setPlaceId( checkplaces[j] );
						
//						i++;
						i = i + chour;
						if( i>cnum ){
							continue;
						}
						arrangeDao.save(arrange2);
						
						classNum++;

						Event event = arrangeToEvent( arrange2 , checkplaces[j] );
						
						evs.add(event);
					}
				}
//				int index = checkdays.indexOf(today.toString());
//				if( index > -1 ){
//					
//				}
				//24 * 60 * 60 * 1000=86400000
				sDate = new Date( sDate.getTime() + 86400000 );
				eDate = new Date( eDate.getTime() + 86400000 );
			}
			return evs;
		}
		else {
			arrangeDao.save(arrange);
			Event event = arrangeToEvent( arrange , arrange.getPlaceId() );
			
			evs.add( event );
			return evs;
		}
	}
	private Event arrangeToEvent( Arrange arrange, Long pid ){
		Event event = new Event();
		Category place = categoryDao.findOne( pid );
		event.setId( arrange.getId() );
		event.setColor( place.getColor() );
		event.setStart( arrange.getStartTime().getTime()/1000 );
		event.setEnd( arrange.getEndTime().getTime()/1000 );
		event.setTextColor( place.getTextColor() );
		
		Category course = categoryDao.findOne(arrange.getCourseId());
		User teacher = userDao.findOne(arrange.getTeacherId());
		String tit = course.getName() + ",No."+arrange.getNumber()+","+teacher.getName();
		Classes classes = classesDao.findOne(arrange.getClassesId());
		if( classes.getIsVIP() ){
			tit = "VIP:"+tit;
		}
		event.setTitle(tit);
		
		return event;
	}
	/**
	 * 每周被选中的日子
	 * @param arrangeLaw
	 * @return
	 */
	private char[] checkedDays( String arrangeLaw ){
		if( StringHelper.isNotEmpty(arrangeLaw) ){
			String[] stp = arrangeLaw.split(",");
			StringBuilder cdays = new StringBuilder(7);
			for (String string : stp) {
				String[] daystp = string.split("-");
				cdays.append(daystp[0]);
			}
			return cdays.toString().toCharArray();
		}
		return null;
	}
	/**
	 * 每周中每天被选中的时间
	 * @param arrangeLaw
	 * @return
	 */
	private Long[] checkedTimes( String arrangeLaw ){
		if( StringHelper.isNotEmpty(arrangeLaw) ){
			String[] stp = arrangeLaw.split(",");
			Long[] times = new Long[7];
			for (int i=0; i<stp.length; i++) {
				String[] daystp = stp[i].split("-");
				times[i] = Long.valueOf(daystp[1]);
			}
			return times;
		}
		return null;
	}
	/**
	 * 每周中每天被选中的授课地点
	 * @param arrangeLaw
	 * @return
	 */
	private Long[] checkedPlaces( String arrangeLaw ){
		if( StringHelper.isNotEmpty(arrangeLaw) ){
			String[] stp = arrangeLaw.split(",");
			Long[] times = new Long[7];
			for (int i=0; i<stp.length; i++) {
				String[] daystp = stp[i].split("-");
				times[i] = Long.valueOf(daystp[2]);
			}
			return times;
		}
		return null;
	}
	
	@Transactional(readOnly = true)
	public List<Event> getArrange( long start , long end , Long uid ){
		
        Date firstTime = new Date(start*1000);
        Date lastTime = new Date(end*1000+86399999);
        
        List<Event> elist = new ArrayList<Event>();
        List<Arrange> list;
        if(uid!=null){
        	list = arrangeDao.findByStartTimeBetweenAndExistStateAndTeacherId(firstTime, lastTime, true, uid );
        }
        else{
        	list = arrangeDao.findByStartTimeBetweenAndExistState(firstTime, lastTime, true);
        }
        
        for (Arrange arrange : list) {
			Event event = new Event();
			
			String course = "_"+arrange.getCourse().getName()+"("+arrange.getCourse().getClassHour()+")";
			String className = arrange.getClasses()!=null?arrange.getClasses().getClassName():"";
			event.setTooltip( className+course+"，No."+arrange.getNumber()+"，"+arrange.getTeacher().getName());
			String tit = arrange.getCourse().getName() + ",No."+arrange.getNumber()+","+arrange.getTeacher().getName();
			if( arrange.getClasses().getIsVIP() ){
				tit = "VIP:"+tit;
			}
			event.setTextColor( arrange.getPlace().getTextColor() );
			event.setTitle( tit );
			event.setColor( arrange.getPlace().getColor() );
			event.setId(arrange.getId());
			
			event.setStart( arrange.getStartTime().getTime()/1000 );
			event.setEnd( arrange.getEndTime().getTime()/1000 );
			
			elist.add(event);
		}
		
		return elist;
	}
	
	@Transactional(readOnly = true)
	public Long[] getCourseNumber(Arrange arrange){
		Long num = arrangeDao.getCourseNumber( arrange.getClassesId(), arrange.getCourseId());
		Category course = categoryDao.findOne(arrange.getCourseId());
		if( num==null || num==0 ){
			return new Long[]{1l,Long.valueOf(course.getClassHour())};
		}
		else{
			return new Long[]{num+1,Long.valueOf(course.getClassHour())};
		}
	}
	
	@Transactional(readOnly = true)
	public Arrange gotoUpdate(Arrange arrange){
		return arrangeDao.findByIdAndExistState(arrange.getId(), true);
	}
	
	public Long deleteArrange(long id){
		arrangeDao.delete(id);
		return id;
	}
	
	public void arrangeDrop(long id, int days, int minutes){
		Arrange arrange = arrangeDao.findOne(id);
		Date sDate = arrange.getStartTime();
		Date eDate = arrange.getEndTime();
		arrange.setStartTime( new Date( sDate.getTime() + days * 24 * 60 * 60 * 1000 + minutes * 60 * 1000 ) );
		arrange.setEndTime( new Date( eDate.getTime() + days * 24 * 60 * 60 * 1000 + minutes * 60 * 1000 ) );
		arrangeDao.save(arrange);
	}
	
	@Transactional(readOnly = true)
	public List<Arrange> searchArrange(final Arrange arrange){
		List<Arrange> aList = arrangeDao.findAll(new Specification<Arrange>() {  
            @Override  
            public Predicate toPredicate(Root<Arrange> root, CriteriaQuery<?> query, CriteriaBuilder cb) {  
                
            	Predicate predicate = null;
            	if( arrange.getStartTime()!=null ){
            		Path<Date> sd = root.get("startTime");
            		predicate = cb.greaterThanOrEqualTo(sd, arrange.getStartTime());
            	}
            	if( arrange.getEndTime()!=null ){
            		Path<Date> ed = root.get("endTime");
            		if(predicate!=null){
            			predicate = cb.and(predicate, cb.lessThanOrEqualTo(ed, arrange.getEndTime()) );
            		}
            		else{
            			predicate = cb.lessThanOrEqualTo(ed, arrange.getEndTime());
            		}
            		
            	}
            	if( arrange.getTeacherId()!=null ){
            		Path<Long> tid = root.get("teacherId");
            		if(predicate!=null){
            			predicate = cb.and(predicate, cb.equal(tid, arrange.getTeacherId()));
            		}
            		else{
            			predicate = cb.equal(tid, arrange.getTeacherId());
            		}
            	}
            	if( arrange.getClassesId()!=null ){
            		Path<Classes> tid = root.get("classes");
            		if(predicate!=null){
            			predicate = cb.and(predicate, cb.equal(tid.get("placeId"), arrange.getClassesId()));
            		}
            		else{
            			predicate = cb.equal(tid.get("placeId"), arrange.getClassesId());
            		}
            	}
            	
                return predicate; 
            }  
  
        }, new Sort(Direction.ASC,"startTime"));
		return aList;
	}
}
